﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HSDc.DefinitionTransformer.DBBoundary
{
    internal class ProcessRepository
    {

        private DBBoundary.FCB_RFlowEntities _context;
        private ProcessElementRepository _procEleRepo;

        public void Add(Entity.Process process) 
        {
            //先save swimlane 在save activey 在 save transition
            
            _context = GetEntities();
            using (System.Transactions.TransactionScope tx = new System.Transactions.TransactionScope())
            {
               
                DoDefinition(process);
                DoProcessElements(process);

                tx.Complete();
            }
     

        }

        private void DoDefinition(Entity.Process process)
        {
            WF_TBL_Definition def = TransferToEOFEntity(process);
            _context.AddToWF_TBL_Definition(def);
            _context.SaveChanges();
            process.EofId = def.Definition_ID;
        
        
        }

        private void DoProcessElements(Entity.Process process)
        {
            _procEleRepo = new ProcessElementRepository(_context , process);
            DoSwimlanes(process);
            DoConnectedElements(process);
            DoTransitions(process);

        }

        private void DoSwimlanes(Entity.Process process) 
        {
            foreach (Entity.Swimlane sw in process.Swimlanes)
                _procEleRepo.Add(sw);
        
        }

        private void DoConnectedElements(Entity.Process process)
        {
            foreach (Entity.ProcessElement item in process.ConnectedElements)
                _procEleRepo.Add(item);

        }

        private void DoTransitions(Entity.Process process)
        {
            int count = 0;
            foreach (Entity.Transition tran in process.Transitions) {
                if (count >= 1) _procEleRepo.Add(tran);
                count += 1;
            }
            

        }

        private DBBoundary.WF_TBL_Definition TransferToEOFEntity(Entity.Process process) 
        {
            //todo Arthur
            DBBoundary.WF_TBL_Definition def = new WF_TBL_Definition();
            def.Definition_GUID = process.Guid;
            def.Definition_Name = process.Name;
            def.Definition_Version = process.Version;
            def.Definition_SOURCE =process.Source;
            def.Definition_STATUS = process.Status;

            return def;
        }   

        private DBBoundary.FCB_RFlowEntities GetEntities()
        {
            String connectionPath = this.GetType().Assembly.CodeBase.Substring(8).Replace("/", "\\");
              FCB_RFlowEntities entities  =
                  new FCB_RFlowEntities(System.Configuration.ConfigurationManager.OpenExeConfiguration(connectionPath).ConnectionStrings.ConnectionStrings["FCB_RFlowEntities"].ConnectionString);
            return entities;
        }


        private  class ProcessElementRepository
        {

            private DBBoundary.FCB_RFlowEntities _context;
            private Entity.Process _process;

            public ProcessElementRepository(DBBoundary.FCB_RFlowEntities context, Entity.Process process) 
            {
                _context = context;
                _process = process;
            }

            public void Add(Entity.ProcessElement  processElement)
            {
                if (processElement.GetType() == typeof(Entity.Swimlane))  DoSwimlane((Entity.Swimlane)processElement);
                if (processElement.GetType() == typeof(Entity.Decision)) DoProcessElement(processElement);

                if (processElement.GetType() == typeof(Entity.EndPoint)) DoProcessElement(processElement);
                if (processElement.GetType() == typeof(Entity.Activity)) DoProcessElement(processElement);
                if (processElement.GetType() == typeof(Entity.Fork)) DoProcessElement(processElement);
                if (processElement.GetType() == typeof(Entity.Join)) DoProcessElement(processElement);
                if (processElement.GetType() == typeof(Entity.Transition)) DoTransition((Entity.Transition)processElement);
            
            }

            private void DoSwimlane(Entity.Swimlane swimlane) 
            {
                DBBoundary.WF_TBL_Swimlane sw = new WF_TBL_Swimlane();
                sw.Swimlane_Definition_ID = _process.EofId;
                sw.Swimlane_GUID = swimlane.Guid;
                sw.Swimlane_Name = swimlane.Name;
                sw.Swimlane_SEQ = swimlane.SeqNo;
                sw.Swimlane_RULE_CLASS = swimlane.RuleClass;
                _context.AddToWF_TBL_Swimlane(sw);
                _context.SaveChanges();
            
            }

            private void DoProcessElement(Entity.ProcessElement processElement)
            {

                DBBoundary.WF_TBL_Activity activity = new WF_TBL_Activity();

                activity.Activity_GUID = processElement.Guid;
                activity.Activity_Name = processElement.Name;
                activity.Actvity_Swimlane = _process.FindElementBelongSwimlane(processElement.ParentId).SeqNo;
                activity.Activity_CLASS = GetActiviyClass(processElement);
                activity.Activity_RULE_CLASS = GetRuleClass(processElement);
                activity.Activity_Belong_Definition = _process.EofId;


                _context.AddToWF_TBL_Activity(activity);
                _context.SaveChanges();

                processElement.EofId = activity.Activity_ID;
            }

            private void DoTransition(Entity.Transition transition)
            {
                DBBoundary.WF_TBL_Transition tran = new WF_TBL_Transition();

                tran.Transition_Constraints = transition.Constraint;
                tran.Transition_GUID = transition.Guid;
                tran.Transition_Source = _process.FindConnectedProcessElement(transition.SourceId).EofId;
                tran.Transition_Target = _process.FindConnectedProcessElement(transition.TargetId).EofId;

                _context.AddToWF_TBL_Transition(tran);
                _context.SaveChanges();

            }

            public string GetActiviyClass(Entity.ProcessElement processElement) 
            {
                if (processElement.GetType() == typeof(Entity.Activity)) return ((Entity.Activity)processElement).ProcessElementClass;
                if (processElement.GetType() == typeof(Entity.Decision)) return ((Entity.Decision)processElement).ProcessElementClass;
                if (processElement.GetType() == typeof(Entity.Fork)) return ((Entity.Fork)processElement).ProcessElementClass;
                if (processElement.GetType() == typeof(Entity.Join)) return ((Entity.Join)processElement).ProcessElementClass;
                if (processElement.GetType() == typeof(Entity.EndPoint)) return ((Entity.EndPoint)processElement).ProcessElementClass;

                return string.Empty;
            
            }

            public string GetRuleClass(Entity.ProcessElement processElement)
            {
                if (processElement.GetType() == typeof(Entity.Decision)) return ((Entity.Decision)processElement).RuleClass;
            
                return string.Empty;

            }

        }




    }

}
